package com.cman777.springc.mybatis.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cman777.springc.common.bean.Iface.EntityIFace;
import com.cman777.springc.common.bean.enums.BaseResultCodeEnum;
import com.cman777.springc.common.helper.EntityUtil;
import com.cman777.springc.common.helper.GenericUtil;
import com.cman777.springc.common.helper.ValidateUtil;
import com.cman777.springc.mybatis.mapper.CustomBaseMapper;
import com.cman777.springc.mybatis.service.BaseService;
import com.cman777.springc.mybatis.util.WrapperUtil;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;


/**
 * @author chenzhicong
 * @time 2020/3/17 8:12
 * @description 重写remove方法是因为逻辑删除时需要更新stateDate与operatorId，
 * mybatisPlus默认的remove无法完成自动填充
 */

public abstract class BaseServiceImpl<T extends EntityIFace, M extends CustomBaseMapper<T>>
        extends ServiceImpl<M, T> implements BaseService<T> {

    @Override
    public int updateAllColumnById(T entity) {
        return this.getBaseMapper().updateAllColumnById(entity);
    }

    @Override
    public boolean removeById(@NotNull Serializable id) {
        ValidateUtil.isTrue(id != null, BaseResultCodeEnum.SYSTEM_ERROR);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        WrapperUtil.handlerUpdateWrapper4LogicRemove(updateWrapper);
        updateWrapper.eq(EntityUtil.getEntityIdColumnName(getEntityClass(this.getClass())), id);
        return this.update(updateWrapper);
    }

    @Override
    public boolean removeByMap(@NotEmpty Map<String, Object> columnMap) {
        ValidateUtil.isTrue(CollectionUtils.isEmpty(columnMap), BaseResultCodeEnum.SYSTEM_ERROR);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        WrapperUtil.handlerUpdateWrapper4LogicRemove(updateWrapper);
        columnMap.forEach((k, v) -> {
                    updateWrapper.eq(k, v);
                }
        );
        return this.update(updateWrapper);
    }

    /**
     * 注：底层有点复杂，没有花很多时间取研究Wrapper的底层，所以这里强制规定传入的是updateWrapper
     */
    @Deprecated
    @Override
    public boolean remove(Wrapper<T> wrapper) {
        ValidateUtil.isTrue(!(wrapper instanceof UpdateWrapper), BaseResultCodeEnum.SYSTEM_ERROR);
        UpdateWrapper<T> updateWrapper = (UpdateWrapper) wrapper;
        WrapperUtil.handlerUpdateWrapper4LogicRemove(updateWrapper);
        return this.update(updateWrapper);

    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return false;
        }
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in(EntityUtil.getEntityIdColumnName(getEntityClass(this.getClass())), idList);
        WrapperUtil.handlerUpdateWrapper4LogicRemove(updateWrapper);
        return this.update(updateWrapper);
    }

    /**
     * 根据baseService实现获取实体类型，注意直接获取父类的实体泛型获取不到，
     * 因为这里可能注入的实际上是Cglib代理类，需要递归的去取父类
     */
    private static Class getEntityClass(Class c) {
        if (c.getSuperclass() == Object.class) {
            return Object.class;
        } else {
            if (c.getSuperclass() == BaseServiceImpl.class) {
                return GenericUtil.getGenericClass(c, 0);
            } else {
                return getEntityClass(c.getSuperclass());
            }
        }
    }




}
